//###############
//FILE : ModifyingCommand.java
//WRITER : Daniel Lowengrub, daniel_i_l, 320687098
//EXERCISE : oop ex3 2011
//DESCRIPTION:
//See below
//###############
package oop.ex3.filemanager;

import oop.ex3.communication.SocketAddress;
import oop.ex3.protocol.sessions.FileContainFileSession;
import oop.ex3.protocol.sessions.FileRemoveFileSession;

/**
 * This is an abstract base class for all FS commands that modify the FS state.
 * It contains all the methods used for notifying NSs of the various changes.
 * @author daniel
 */
public abstract class ModifyingCommand extends UserCommand {
    private static final long WAIT_TIME = 100;
    protected NameServerConnection _connection;
    protected FileDatabase _fileDatabase;
    protected NameServerDatabase _nameServers;

    /**
     * Construct a modifying command with a command name and connection used for talking
     * with NS.
     * @param commandName The command name.
     * @param connection The connection to use.
     */
    public ModifyingCommand(String commandName, NameServerConnection connection) {
        super(commandName);
        _connection = connection;
        _fileDatabase = _connection.getFileDatabase();
        _nameServers = _connection.getNameServerDatabase();
    }

    /**
     * Notify a NS that a file has been added.
     * @param nameServer The server to notify.
     * @param fileName The name of the added file.
     */
    protected void notifyNameServerAddition (SocketAddress nameServer, String fileName) {
        if (!_connection.initializeStreams(nameServer))
            return;

        FileContainFileSession addSession = new FileContainFileSession();
        _connection.initializeSession(addSession);
        addSession.setFileName(fileName);
        addSession.executeSession(_connection.getInputStream(), _connection.getOutputStream());

        _connection.closeConnection();
    }

    /**
     * Notify a NS that a file has been removed.
     * @param nameServer The server to notify.
     * @param fileName The name of the removed file.
     */
    protected void notifyNameServerRemoval (SocketAddress nameServer, String fileName) {
        if (!_connection.initializeStreams(nameServer))
            return;

        FileRemoveFileSession session = new FileRemoveFileSession();
        _connection.initializeSession(session);
        session.setFileName(fileName);
        session.executeSession(_connection.getInputStream(), _connection.getOutputStream());

        _connection.closeConnection();
    }

    /**
     * Wait for all of the current FS uploads to finish. This should be call before
     * removing or renaming files.
     * @param fileName
     */
    protected void waitForUploads(String fileName) {
        //System.out.println("waiting for " + _fileDatabase.getNumberOfStreams(fileName) + " uploads");
        while (_fileDatabase.currentlyStreaming(fileName)) {//while the file is being streamed
            try {
                //while the file is being streamed
                Thread.sleep(WAIT_TIME);
            } catch (InterruptedException ex) {
                //if we're interupted then just check again
            }
        }

        //System.out.println("finished waiting");
    }
}
